<?php
/**
 * 将Base64图片数据保存为文件
 * @param string $base64Data Base64编码的图片数据（可带或不带前缀）
 * @param string $outputPath 输出文件路径（如："./images/photo.jpg"）
 * @return bool 是否保存成功
 */
function base64ToImage($base64Data, $outputPath)
{
    // 移除Base64前缀（如 "data:image/png;base64,"）
    if (strpos($base64Data, ';base64,') !== false) {
        $base64Data = explode(',', $base64Data)[1];
    }

    // 解码Base64数据
    $imageData = base64_decode($base64Data);
    if ($imageData === false) {
        throw new Exception("Base64解码失败");
    }

    // 确保目录存在
    $dir = dirname($outputPath);
    if (!is_dir($dir)) {
        mkdir($dir, 0755, true);
    }

    // 保存文件
    return file_put_contents($outputPath, $imageData) !== false;
}

/**
 * https://www.volcengine.com/docs/86081/1804560#Zp7fWyKD
 * [request description]
 * @param  [type] $method  [description]
 * @param  [type] $query   [description]
 * @param  [type] $header  [description]
 * @param  [type] $ak      [description]
 * @param  [type] $sk      [description]
 * @param  [type] $action  [description]
 * @param  [type] $version [description]
 * @param  [type] $body    [description]
 * @return [type]          [description]
 */
function requestVolcengineapi($method, $query, $header, $action, $version, $body)
{
    $AccessKeyID     = 'AKLTZWFjNWIzY2VhYjBjNDg5NzkwMDQ5MjJmMWNkMmJlNjQ';
    $SecretAccessKey = 'T0RJeVlUQmtOVEV6WlRVeU5HTmhabUkwWTJRMU16RXhaamd5TVRZMk16Yw==';
    // 第二步：创建身份证明。其中的 Service 和 Region 字段是固定的。ak 和 sk 分别代表
    // AccessKeyID 和 SecretAccessKey。同时需要初始化签名结构体。一些签名计算时需要的属性也在这里处理。
    // 初始化身份证明结构体
    $Host        = "visual.volcengineapi.com";
    $ContentType = "application/json";
    $Service     = "cv";
    $Region      = "cn-north-1";
    $credential  = [
        'accessKeyId' => $AccessKeyID,
        'secretKeyId' => $SecretAccessKey,
        'service'     => $Service,
        'region'      => $Region,
    ];
    // 初始化签名结构体
    $query = array_merge($query, [
        'Action'  => $action,
        'Version' => $version,
    ]);
    ksort($query);
    $requestParam = [
        // body是http请求需要的原生body
        'body'        => $body,
        'host'        => $Host,
        'path'        => '/',
        'method'      => $method,
        'contentType' => $ContentType,
        'date'        => gmdate('Ymd\THis\Z'),
        'query'       => $query,
    ];
    // 第三步：接下来开始计算签名。在计算签名前，先准备好用于接收签算结果的 signResult 变量，并设置一些参数。
    // 初始化签名结果的结构体
    $xDate          = $requestParam['date'];
    $shortXDate     = substr($xDate, 0, 8);
    $xContentSha256 = hash('sha256', $requestParam['body']);
    $signResult     = [
        'Host'             => $requestParam['host'],
        'X-Content-Sha256' => $xContentSha256,
        'X-Date'           => $xDate,
        'Content-Type'     => $requestParam['contentType'],
    ];
    // 第四步：计算 Signature 签名。
    $signedHeaderStr     = join(';', ['content-type', 'host', 'x-content-sha256', 'x-date']);
    $canonicalRequestStr = join("\n", [
        $requestParam['method'],
        $requestParam['path'],
        http_build_query($requestParam['query']),
        join("\n", ['content-type:' . $requestParam['contentType'], 'host:' . $requestParam['host'], 'x-content-sha256:' . $xContentSha256, 'x-date:' . $xDate]),
        '',
        $signedHeaderStr,
        $xContentSha256,
    ]);
    $hashedCanonicalRequest      = hash("sha256", $canonicalRequestStr);
    $credentialScope             = join('/', [$shortXDate, $credential['region'], $credential['service'], 'request']);
    $stringToSign                = join("\n", ['HMAC-SHA256', $xDate, $credentialScope, $hashedCanonicalRequest]);
    $kDate                       = hash_hmac("sha256", $shortXDate, $credential['secretKeyId'], true);
    $kRegion                     = hash_hmac("sha256", $credential['region'], $kDate, true);
    $kService                    = hash_hmac("sha256", $credential['service'], $kRegion, true);
    $kSigning                    = hash_hmac("sha256", 'request', $kService, true);
    $signature                   = hash_hmac("sha256", $stringToSign, $kSigning);
    $signResult['Authorization'] = sprintf("HMAC-SHA256 Credential=%s, SignedHeaders=%s, Signature=%s", $credential['accessKeyId'] . '/' . $credentialScope, $signedHeaderStr, $signature);
    $header                      = array_merge($header, $signResult);
    // 4. 转换头信息格式
    $headerLines = [];
    foreach ($header as $k => $v) {
        $headerLines[] = "$k: $v";
    }
    // 第五步：将 Signature 签名写入 HTTP Header 中，并发送 HTTP 请求。

    $url     = 'https://' . $requestParam['host'] . $requestParam['path'] . '?' . http_build_query($requestParam['query']);
    $context = stream_context_create([
        'http' => [
            'method'        => $method,
            'header'        => implode("\r\n", $headerLines),
            'content'       => $requestParam['body'],
            'ignore_errors' => true,
            'timeout'       => 120,
        ],
        'ssl'  => [
            'verify_peer'      => false,
            'verify_peer_name' => false,
        ],
    ]);

    $response = file_get_contents($url, false, $context);
    return $response;
}

function CVSync2AsyncTask($image, $prompt, $gen_mode = '', $generateSize = [])
{
    $action  = "CVSync2AsyncSubmitTask";
    $version = "2022-08-31";

    // 参考接口文档Body参数
    $requestBody = [
        "req_key"     => "i2i_portrait_photo", //服务标识 固定值
        "image_input" => $image,
        "prompt"      => $prompt, //生图提示词
        "gpen"        => 0.4, //高清处理效果，越高人脸清晰度越高，建议使用默认值
        "skin"        => 0.3, //人脸美化效果，越高美颜效果越明显，建议使用默认值
        "skin_unifi"  => 0, //匀肤效果 ，越高均匀肤色去除瑕疵效果越明显，建议使用默认值
        "width"       => $generateSize['width'] ?? 1024,
        "height"      => $generateSize['height'] ?? 1024,
        "gen_mode"    => $gen_mode, //"creative"：提示词模式  "reference"：全参考模式
        "seed"        => -1,
    ];

    $body = json_encode($requestBody);

    $response = requestVolcengineapi("POST", [], [], $action, $version, $body);
    $response = json_decode($response, true);

    return $response;
}

function CVSync2AsyncGetResult($task_id)
{
    $action  = "CVSync2AsyncGetResult";
    $version = "2022-08-31";

    // 参考接口文档Body参数
    $requestBody = [
        "req_key"    => "i2i_portrait_photo", //服务标识 固定值
        "task_id"    => $task_id,
        "return_url" => true,
    ];
    $body = json_encode($requestBody);

    $response = requestVolcengineapi("POST", [], [], $action, $version, $body);
    $response = json_decode($response, true);

    return $response;
}

/**
 * 获取所有图片比例配置（含动态计算的原图尺寸）
 * @return array
 */
function getImageSizeConfig($ration, $image)
{
    $e = [
        'original' => [
            'label'  => '原图',
            'width'  => null, // 动态计算
            'height' => null, // 动态计算
        ],
        '1:1'      => [
            'label'  => '正方形',
            'width'  => 1328,
            'height' => 1328,
        ],
        '2:3'      => [
            'label'  => '竖图(2:3)',
            'width'  => 885,
            'height' => 1328,
        ],
        '3:2'      => [
            'label'  => '横图(3:2)',
            'width'  => 1328,
            'height' => 885,
        ],
        '3:4'      => [
            'label'  => '竖图(3:4)',
            'width'  => 996,
            'height' => 1328,
        ],
        '4:3'      => [
            'label'  => '横图(4:3)',
            'width'  => 1328,
            'height' => 996,
        ],
        '9:16'     => [
            'label'  => '竖图(9:16)',
            'width'  => 747,
            'height' => 1328,
        ],
        '16:9'     => [
            'label'  => '横图(16:9)',
            'width'  => 1328,
            'height' => 747,
        ],
        '9:21'     => [
            'label'  => '竖图(9:21)',
            'width'  => 569,
            'height' => 1328,
        ],
        '21:9'     => [
            'label'  => '横图(21:9)',
            'width'  => 1328,
            'height' => 569,
        ],
    ];

    if ($ration == 'original') {
        return calculateOriginalImageSize($image);
    } else {
        return $e[$ration];
    }
}

/**
 * 计算原图缩放后的尺寸，确保宽高在 [512, 2048] 范围内
 * @param string $imagePath 图片路径
 * @return array ['width' => int, 'height' => int] 调整后的尺寸
 */
function calculateOriginalImageSize($imagePath)
{
    list($originalWidth, $originalHeight) = getimagesize(getLocalImagePath($imagePath));
    // 如果原图尺寸已经在允许范围内，直接返回
    if ($originalWidth >= 512 && $originalWidth <= 2048 &&
        $originalHeight >= 512 && $originalHeight <= 2048) {
        return [
            'width'  => $originalWidth,
            'height' => $originalHeight,
        ];
    }

    // 计算缩放比例
    $scale = 1.0;

    // 如果宽度或高度超过 2048，按比例缩小
    if ($originalWidth > 2048 || $originalHeight > 2048) {
        $scale = min(2048 / $originalWidth, 2048 / $originalHeight);
    }
    // 如果宽度或高度小于 512，按比例放大
    elseif ($originalWidth < 512 || $originalHeight < 512) {
        $scale = max(512 / $originalWidth, 512 / $originalHeight);
    }

    // 计算调整后的尺寸
    $newWidth  = round($originalWidth * $scale);
    $newHeight = round($originalHeight * $scale);

    return [
        'width'  => $newWidth,
        'height' => $newHeight,
    ];
}

function getLocalImagePath($imageUrl)
{
    $relativePath = parse_url($imageUrl, PHP_URL_PATH);
    return base_path() . '/public' . $relativePath;
}


function getReward($count = false) {
    $data = [
        ['count' => 1, 'reward' => 1, 'completed' => false],
        ['count' => 2, 'reward' => 1, 'completed' => false],
        ['count' => 3, 'reward' => 1, 'completed' => false],
        ['count' => 4, 'reward' => 1, 'completed' => false],
        ['count' => 5, 'reward' => 1, 'completed' => false],
        ['count' => 6, 'reward' => 2, 'completed' => false],
        ['count' => 7, 'reward' => 3, 'completed' => false],
    ];

    if($count) {
        foreach($data as $v){
            if($v['count'] == $count) {
                return $v['reward'];
            }
        }

        return false;
    } else {
        return $data;
    }
}